import NextName from '@/utils/nextName';

const defineVars = function defineVars(node, env) {
  const vars = {};
  let str = '';
  let item;
  for (item of node.body) {
    if (item.type === 'VariableDeclaration') {
      const type = item.kind;
      const list = item.declarations.map(x => ps.process(x, env));
      if (!vars[type]) vars[type] = [];
      vars[type] = vars[type].concat(list);
    }
  }
  for (let type in vars) {
    const list = vars[type];
    str += (type + ' ' + list.map((x) => {
      if (x[1] != null) {
        return x[0] + '=' + x[1];
      }
      return x[0];
    }).join(','));
  }
  return str || null; // return null if no vars are defined
};

const preProcessVars = function preProcessVars(node, env) {
  return defineVars(node, env);
};

const joinCode = function joinCode(list) {
  // TODO: while和if之间的;也可以去除
  return list.filter(x => x != null).join(';');
};

const ps = {
  init(env) {
    env.stack = [];
    // TODO: nested scope
    env.nextName = new NextName();
  },
  Program(node, env) {
    let result = [];
    let item;
    result.push(preProcessVars(node, env));
    for (item of node.body) {
      result.push(ps.process(item, env));
    }
    env.result = result;
    return joinCode(result);
  },
  VariableDeclaration(node, env) {
    return null;
  },
  VariableDeclarator(node, env) {
    return [ps.process(node.id, env), node.init && ps.process(node.init, env)];
  },
  Identifier(node, env) {
    return env.nextName.getName(node.name);
  },
  Literal(node, env) {
    // 压缩true和false
    if (node.raw === 'true') return '!0';
    if (node.raw === 'false') return '!1';
    return node.raw;
  },
  WhileStatement(node, env) {
    const test = ps.process(node.test, env);
    const body = ps.process(node.body, env);
    return `while(${test}){${body}}`;
  },
  IfStatement(node, env) {
    const test = ps.process(node.test, env);
    const consequent = ps.process(node.consequent, env);
    let str = `if(${test}){${consequent}}`;
    const alternate = ps.process(node.alternate, env)
    if (node.alternate) str += `else{${alternate}}`;
    return str;
  },
  BinaryExpression(node, env) {
    return ps.process(node.left, env) + node.operator + ps.process(node.right, env);
  },
  BlockStatement(node, env) {
    const result = [];
    let item;
    result.push(preProcessVars(node, env));
    for (item of node.body) {
      result.push(ps.process(item, env));
    }
    return joinCode(result);
  },
  ExpressionStatement(node, env) {
    return ps.process(node.expression, env);
  },
  AssignmentExpression(node, env) {
    return ps.process(node.left, env) + node.operator + ps.process(node.right, env);
  },
  process(node, env) {
    const p = ps[node.type];
    if (!p) {
      console.error('未处理的类型', node.type, node);
      return;
    }
    const result = p(node, env);
    return result;
  },
};

export default ps;
